Skip to content

Conversation

@lsm5
Copy link
Member

@lsm5 lsm5 commented Nov 17, 2025

See individual commits.

Vendored by containers/skopeo#2747

@github-actions github-actions bot added the image Related to "image" package label Nov 17, 2025
podmanbot pushed a commit to podmanbot/buildah that referenced this pull request Nov 17, 2025
@podmanbot
Copy link

✅ A new PR has been created in buildah to vendor these changes: containers/buildah#6507

@packit-as-a-service
Copy link

Packit jobs failed. @containers/packit-build please check.

@lsm5
Copy link
Member Author

lsm5 commented Nov 17, 2025

/packit rebuild-failed

@lsm5 lsm5 marked this pull request as ready for review November 17, 2025 20:56
@lsm5
Copy link
Member Author

lsm5 commented Nov 17, 2025

@mtrmac PTAL

Copy link
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

ACK to the image part; the dir: part needs a bit more.

}()

digester, stream := putblobdigest.DigestIfCanonicalUnknown(stream, inputInfo)
digester, stream := putblobdigest.DigestIfUnknown(stream, inputInfo)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the destination-transport-side digest computation must be a more complex logic, see in the earlier PR about the interaction with cannotModifyManifestReason.

… and dirReference.layerPath discards the algorithm name; that does not generalize for other algorithms, we need to move towards agility where adding an extra algorithm is a ~parameter change and does not require any more changes to the “code proper”; i.e. discarding algorithm names is no longer much of an option.

(We need to keep the existing file names for sha256, to retain compatibility. And… do we define a new value for versionPath?!)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated PutBlob to store blob under provided digest algorithm with the algorithm name prepended (except for Canonical) along with a canonical digest hardlink.

$ /usr/bin/ls
dc518581817f4e75a7dcfd35383e67c3ef85438250c17e10090b5a31ab8f68d4  manifest.json  sha512-2ee373e378345b35e7966a106c5c0a40a005a13bfc87695d89c5bb217f969c351e73810cf78d3d841237098731cf76878f05af8f8d28176c316681f9422ff688  version

$ diff dc518581817f4e75a7dcfd35383e67c3ef85438250c17e10090b5a31ab8f68d4 sha512-2ee373e378345b35e7966a106c5c0a40a005a13bfc87695d89c5bb217f969c351e73810cf78d3d841237098731cf76878f05af8f8d28176c316681f9422ff688
$

do we define a new value for versionPath?!)

Doesn't break existing behaviour but there's new stuff, so maybe we should? I'll defer to you.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Hard links are not supported by all file systems (FAT)
  • Symbolic links are not supported by all file systems either, and generally restricted to admin users on Windows

And, anyway, readers of dir: can only start with the manifest, and the values provided in the manifest. So if PutBlob returns sha512, and the manifest is written to include sha512, readers will not know the sha256 value and have no way to use it.

So I don’t think we need to compute both digests at all; just the layerPath changes to the path computation, + some (as-yet-undefined) logic for PutBlob to use “the algorithm the user wanted”, should be sufficient.

do we define a new value for versionPath?!)

I think with the changes to layerPath, we need to. Previously it was, hypothetically, possible to read a complete sha512 image from dir:, and those images will now break. And we will need to update both dir…Dest… and dir…Src…: destinations should refuse to work on future versions, and still assign the existing 1.1 version for sha256 images for maximum compatibility. sources should detect+refuse future versions.

Consider making the dir changes a separate PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll keep the dir changes here because of the review comments. Separate PR for image/internal at #486

@lsm5 lsm5 marked this pull request as draft November 19, 2025 13:42
podmanbot pushed a commit to podmanbot/buildah that referenced this pull request Nov 19, 2025
@lsm5 lsm5 marked this pull request as ready for review November 19, 2025 21:35
@lsm5
Copy link
Member Author

lsm5 commented Nov 19, 2025

@mtrmac PTA(nother)L . I think I have addressed all comments so far. Used Claude too, but hopefully no AI slop this time 🤞 . LMK.

Copy link
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The internal/image part LGTM.

}()

digester, stream := putblobdigest.DigestIfCanonicalUnknown(stream, inputInfo)
digester, stream := putblobdigest.DigestIfUnknown(stream, inputInfo)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Hard links are not supported by all file systems (FAT)
  • Symbolic links are not supported by all file systems either, and generally restricted to admin users on Windows

And, anyway, readers of dir: can only start with the manifest, and the values provided in the manifest. So if PutBlob returns sha512, and the manifest is written to include sha512, readers will not know the sha256 value and have no way to use it.

So I don’t think we need to compute both digests at all; just the layerPath changes to the path computation, + some (as-yet-undefined) logic for PutBlob to use “the algorithm the user wanted”, should be sufficient.

do we define a new value for versionPath?!)

I think with the changes to layerPath, we need to. Previously it was, hypothetically, possible to read a complete sha512 image from dir:, and those images will now break. And we will need to update both dir…Dest… and dir…Src…: destinations should refuse to work on future versions, and still assign the existing 1.1 version for sha256 images for maximum compatibility. sources should detect+refuse future versions.

Consider making the dir changes a separate PR.

podmanbot pushed a commit to podmanbot/buildah that referenced this pull request Nov 25, 2025
podmanbot pushed a commit to podmanbot/buildah that referenced this pull request Nov 25, 2025
Copy link
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Just a brief skim…)

if d.Algorithm() == digest.Canonical {
filename = d.Encoded()
} else {
filename = d.Algorithm().String() + "-" + d.Encoded()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether we need to do a version check and conditionally use the old logic here. I guess that doesn’t matter in practice.

@lsm5 lsm5 marked this pull request as draft November 26, 2025 15:09
podmanbot pushed a commit to podmanbot/buildah that referenced this pull request Nov 26, 2025
@lsm5 lsm5 marked this pull request as ready for review November 26, 2025 15:58
@lsm5
Copy link
Member Author

lsm5 commented Nov 26, 2025

good for another look.

Copy link
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A full review now. ACK to the feature set.

var ErrNotContainerImageDir = errors.New("not a containers image directory, don't want to overwrite important data")

// ErrUnsupportedVersion indicates that the directory uses a version newer than we support
var ErrUnsupportedVersion = errors.New("unsupported directory transport version")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works but prevents us from adding more data to the error in the future as an API (e.g. path, the version). type UnsupportedVersionError struct{}, at least? Yes, there’s a pre-existing instance just above…

return private.UploadedBlob{}, err
}

if blobDigest.Algorithm() != digest.Canonical {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The placement in the ~middle of “finishing a file write” is a bit unintuitive. Either before the Sync, or maybe just before the Rename (but the succeeded logic makes that placement imprecise).

func (d *dirImageDestination) CommitWithOptions(ctx context.Context, options private.CommitOptions) error {
versionToWrite := version1_1
if d.usesNonSHA256Digest {
versionToWrite = version
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks confusing — better to name the new one version1_2 explicitly.

assert.Equal(t, signatures, sigs)
}

func TestVersionAssignment(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Let’s move closer to a typical structure — place this in directory_dest_test.go, please
  • This can be much shorter as a table-driven test (list of algorithms -> expected version)

if string(contents) != version {
versionStr := string(contents)
if versionStr != version && versionStr != version1_1 {
if versionStr > version {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m not much of a fan of this lexicographic comparison — I think it might be time to start explicitly parsing into ([prefix must match], major, minor), and formatting from integers into strings as well — but at the very least please factor this comparison (“isUnsupportedVersion??”) into a single function shared between sources and destinations.

Maybe share the whole reading + parsing of the file into (major, minor)… that would be more ceremony.

@lsm5 lsm5 marked this pull request as draft November 27, 2025 19:38
podmanbot pushed a commit to podmanbot/buildah that referenced this pull request Nov 27, 2025
When storing blobs with non-canonical digest algorithms (e.g., sha512),
store the blob under the provided digest algorithm with an algorithm
prefix (e.g., "sha512-abc" instead of just "abc").

SHA256 (canonical) digests continue to be stored without a prefix for
backward compatibility.

Signed-off-by: Lokesh Mandvekar <[email protected]>
Introduce version 1.2 and dynamically assign versions based on the digest
algorithms used:
- Version 1.1 for sha256-only images (backward compatibility)
- Version 1.2 for images using non-sha256 digest algorithms (e.g., sha512)

Add validation in both ImageDestination and ImageSource to:
- Assume 1.1 if no version file found in dir transport images
- Accept both version 1.1 and 1.2
- Refuse unsupported future versions

Co-authored-by: Miloslav Trmač <[email protected]>
Signed-off-by: Lokesh Mandvekar <[email protected]>
podmanbot pushed a commit to podmanbot/buildah that referenced this pull request Nov 27, 2025
@lsm5 lsm5 marked this pull request as ready for review November 27, 2025 21:34
@lsm5
Copy link
Member Author

lsm5 commented Nov 27, 2025

@mtrmac good for another look. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

image Related to "image" package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants